package okl.test.motionChart.renderers
{
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.setTimeout;
	
	import mx.binding.utils.BindingUtils;
	import mx.charts.DateTimeAxis;
	import mx.charts.chartClasses.DualStyleObject;
	import mx.charts.chartClasses.IAxis;
	import mx.charts.chartClasses.IAxisRenderer;
	import mx.containers.Box;
	import mx.containers.Canvas;
	import mx.containers.HBox;
	import mx.controls.Button;
	import mx.core.Container;
	import mx.effects.AnimateProperty;
	import mx.events.CollectionEvent;
	import mx.events.DynamicEvent;
	import mx.events.EffectEvent;
	import mx.events.FlexEvent;
	import mx.events.SliderEvent;
	import mx.formatters.DateFormatter;
	import mx.graphics.IStroke;
	
	import okl.test.motionChart.BubbleChartDescriptor;
	import okl.test.motionChart.skins.SpeedSliderThumbSkin;
	import okl.test.motionChart.skins.TimePlayButtonSkin;
	import okl.test.motionChart.skins.TimePlayToggleButtonSkin;
	
	import spark.components.Group;
	import spark.components.HGroup;
	import spark.components.HSlider;
	import spark.components.NavigatorContent;
	import spark.components.VGroup;
	import spark.components.VSlider;
	import okl.test.motionChart.skins.SpeedSliderSkin;
	import okl.test.motionChart.skins.TimeAxisSlider;
	import spark.layouts.HorizontalLayout;
	
	public class TimePlayAxisRenderer extends DualStyleObject implements IAxisRenderer
	{
		private var df:DateFormatter = new DateFormatter();
		private function dataTipFormatFunction(item:Object):String{return df.format(new Date(item));}
		private var _slider:HSlider;
		private var _btnPlay:Button;
		private var eff:AnimateProperty;
		private var _speedSlider:VSlider;
		private var _sliderSet:Boolean;
		
		private var _desc:BubbleChartDescriptor;
		public function TimePlayAxisRenderer()
		{
			super();
			df.formatString="DD/MM/YY"
		}

		//{region LIFE_CYCLE
		private static const W_HEIGHT:Number = 60;
		private static const SLIDER_HEIGHT:Number = 20;
		private static const MARGIN_TOP:Number = 10;
		private static const GAP:Number = 10;
		override protected function createChildren():void{
			super.createChildren();
						
			_btnPlay = new Button();
			_btnPlay.setStyle("skin", TimePlayToggleButtonSkin);
			_btnPlay.toggle = true;			
			_btnPlay.addEventListener(MouseEvent.CLICK, onPlayClick);
			_btnPlay.width=_btnPlay.height=W_HEIGHT*0.9;
			this.addChild(_btnPlay);
			
			_slider = new HSlider();
			_slider.setStyle("skinClass", TimeAxisSlider);			
			_slider.dataTipFormatFunction = dataTipFormatFunction;
			_slider.showDataTip = false;
			_slider.height = SLIDER_HEIGHT;			
			this.addChild(_slider);
			_slider.addEventListener(SliderEvent.CHANGE,  onSliderValueChanged);
			_slider.addEventListener(FlexEvent.VALUE_COMMIT, onSliderValueCommit);
			
			_speedSlider = new VSlider();
			_speedSlider.setStyle("skinClass", SpeedSliderSkin);
			_speedSlider.addEventListener(SliderEvent.CHANGE, onSpeedChange);			
			_speedSlider.snapInterval=1;
			_speedSlider.minimum=0;
			_speedSlider.maximum=2;
			_speedSlider.setStyle("tickLength", 5);
			_speedSlider.value=1;
			_speedSlider.setActualSize(15, W_HEIGHT);	
			this.addChild(_speedSlider);

			initEffect();
		}
		
	
		override protected function commitProperties():void{
			super.commitProperties();
		
			if(__selectedDateDirty){
				_slider.value = _selectedDate.time;
				__selectedDateDirty=false;
			}	
		}
		

		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			//placing of axis elements, by default axisrenderer use whole chart estate
			var baseFrame:Rectangle = new Rectangle(
				GAP, unscaledHeight-W_HEIGHT-MARGIN_TOP, 
				unscaledWidth-GAP-gutters.right, W_HEIGHT
			); 
		
			//layout children manually. The most simple way would be to place them in HBOX/GRoup, but for some reason was not able to layout them
			_btnPlay.move(baseFrame.x, baseFrame.y + (baseFrame.height-_btnPlay.height)/2);
			var tempX:Number = (GAP + _btnPlay.x+_btnPlay.width);
			_speedSlider.move(tempX + (gutters.left-tempX-_speedSlider.width)/2, baseFrame.y + (baseFrame.height-_speedSlider.height)/2);
			_slider.move(gutters.left, baseFrame.y + (baseFrame.height-_slider.height)/2);
			//always should be equal to chart area width
			_slider.width = unscaledWidth-gutters.left-gutters.right;
			
			//temp
			_slider.minimum = timeAxis.minimum.time;
			_slider.maximum = timeAxis.maximum.time;
		
		}
		
	
		

		
		protected function onSpeedChange(event:Event):void{
			_speedRatio = _speedSlider.value;
			if(eff.isPlaying){
				timelinePlay();
			}
		}
		
		public static const EVT_DATE_CHANGE:String="dateChange";
		protected function onSliderValueCommit(event:Event):void{
			var targetDate:Date = new Date(_slider.value);
			var targetEvent:DynamicEvent = new DynamicEvent(EVT_DATE_CHANGE);
			targetEvent.date = targetDate;
			targetEvent.temp = (_slider.value-_slider.minimum)/(_slider.maximum-_slider.minimum)
			dispatchEvent(targetEvent);
		}
		
		
		private var _selectedDate:Date, __selectedDateDirty:Boolean;
		public function set selectedDate(value:Date):void{
			if(_selectedDate==value)return;
			_selectedDate=value;
			__selectedDateDirty=true;
			invalidateProperties();
		}
		
		
		
		
		//{region ILOGIC
		private function get timeAxis():DateTimeAxis{return axis as DateTimeAxis;}
		private var _axis:IAxis, __axisDirty:Boolean;
		public function get axis():IAxis
		{
			return _axis;
		}
		
		public function set axis(value:IAxis):void
		{
			_axis=value;
			__axisDirty=true;
			invalidateProperties();
		}
		
		private var _gutters:Rectangle;
		public function get gutters():Rectangle
		{
			return _gutters;
		}
		
		public function set gutters(value:Rectangle):void
		{
			_gutters=value;
		}
		
		public function set heightLimit(value:Number):void
		{
		}
		
		public function get heightLimit():Number
		{
			return 0;
		}
		
		public function get horizontal():Boolean
		{
			return false;
		}
		
		public function set horizontal(value:Boolean):void
		{
		}
		
		public function get minorTicks():Array
		{
			return null;
		}
		
		public function set otherAxes(value:Array):void
		{
		}
		
		public function get placement():String
		{
			return null;
		}
		
		public function set placement(value:String):void
		{
		}
		
		public function get ticks():Array
		{
			return null;
		}
		
		public function adjustGutters(workingGutters:Rectangle, adjustable:Object):Rectangle
		{
			return workingGutters;
		}
		
		public function chartStateChanged(oldState:uint, v:uint):void{
		
		}
		//}endregion
		
		//{region EFFECT
		private static var DEFAULT_SPEED:Number=10000; /* 10 seconds to play whole */
		private var _speedRatio:Number=1;
		private function initEffect():void{
			eff = new AnimateProperty(_slider);
			eff.addEventListener(EffectEvent.EFFECT_END, onEffectEnd);
			eff.addEventListener(EffectEvent.EFFECT_STOP, onEffectStop);
			eff.addEventListener(EffectEvent.EFFECT_START, onEffectStart);
			eff.property="value";
		}
		
		protected function onEffectStart(event:Event):void{
			_btnPlay.selected = true;
		}		
		protected function onEffectEnd(event:Event):void{
			_btnPlay.selected = false;
		}		
		protected function onEffectStop(event:Event):void{
			_btnPlay.selected = false;
		}
		
		protected function onSliderValueChanged(event:Event):void{
			if(eff.isPlaying){
				timelinePlay();
			}			
		}
		
		private function onPlayClick(skipEvent:Event):void{
			if(_btnPlay.selected){
				timelinePlay();
			}else{
				eff.stop();
			}			
		}
		
		private function timelinePlay():void{
			if(eff.isPlaying)eff.stop();			
			if(_slider.value==_slider.maximum){
				_slider.value=_slider.minimum;
			}
			eff.fromValue = _slider.value;
			eff.toValue = _slider.maximum;
			
			var sliderFractionLeft:Number = 1 - (_slider.value-_slider.minimum)/(_slider.maximum - _slider.minimum) ;
			eff.duration = (DEFAULT_SPEED * sliderFractionLeft)/_speedRatio; 
			eff.startDelay = 300;
			eff.play();
		}
		//}endregion
	}
}